Compilers transform computer source code from high-level programming languages to machine code. A common method of compiler construction compiles the source code into an intermediate language, which is then itself compiled into object or machine code. Early compilers type-checked the source language during the initial compilation, and then threw away the type information, leaving the intermediate language untyped. But, maintaining type information within the intermediate compiler representation has significant benefits.
For instance, a typed intermediate language allows intermediate program representations to be themselves type-checked. Errors in the types found at the intermediate level can often be traced to compiler errors, and, thus, can be used to debug the compilers, an otherwise arduous task. Furthermore, the typed intermediate representations can often be more effectively optimized at the machine code level, and safety proofs for the underlying programs can be more easily created. Moreover, typed intermediate representations can be used as a format for redistributing programs, and a user can (mechanically) check that the program redistributed in the intermediate form is safe to run, as opposed to relying on certificates or third party claims of trustworthiness.
One reason that compilers for object-oriented languages have failed to adopt compilation using typed intermediate representations is that traditional class and object encodings have been seen as too complex to type effectively at an intermediate level. Even though work has been done for developing typed intermediate languages for functional languages, much of this work does not support object-oriented programming languages.
Thus far, those typed intermediate languages that have been proposed for object-oriented languages are complicated, often inefficient, and do not allow compilers to use standard implementation techniques. In short, they are not suitable for practical compilers. Furthermore, those typed intermediate languages which do exist do not support more complex object oriented behaviors such as multiple inheritance, and even more complex systems such as multiple inheritance using virtual base classes. With virtual inheritance, a shared copy of a superclass is allowed in a subclass object when the subclass inherits the superclass more than once.
A practical compiler requires simple, general, and efficient type systems. First, compiler writers who are not type theorists should be able to understand the type system. Second, the type system needs to cover a large set of realistic object-oriented language features and compiler transformations. Third, the type system needs to express standard implementation techniques without introducing extra runtime overhead. Fourth, the type system needs to support complex and powerful object oriented language components such as multiple inheritance using virtual base classes. To enable any of the above at the intermediate language level, methods and systems are needed to maintain type information in the intermediate language compiled from a source code representation.